﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;


using MongoDB.Driver;
using MongoDB.Bson;
using MongoDB.Driver.Linq;
using MongoDB.Driver.Builders;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson.Serialization;

namespace duanzhi.web.Models
{
    public class DataSession<D,T>
        where D : MongoDataContext, new()
        where T : MongoDocument,new()
        {
        /// <summary>
        /// IQueryable 只能查询
        /// </summary>
        public IQueryable<T> query { get; set; }
        /// <summary>
        /// MongoCollection
        /// </summary>
        public MongoCollection<T> Mquery { set; get; }
        public MongoDataContext db = new D();
        public DataSession() {

            Mquery = db.mdb.GetCollection<T>(typeof(T).Name);
            if (Mquery == null)
            {
                db.mdb.CreateCollection(typeof(T).Name);
                Mquery = db.mdb.GetCollection<T>(typeof(T).Name);
                
            }
            query = Mquery.AsQueryable();
        }
        /// <summary>
        /// IQueryable查询
        /// </summary>
        /// <param name="lambda"></param>
        /// <returns></returns>
        public IQueryable<T> Where(System.Linq.Expressions.Expression<Func<T, Boolean>> lambda)
        {
            return Mquery.AsQueryable<T>().Where(lambda);
        }
        /// <summary>
        /// 原生MongoCollection查询
        /// </summary>
        /// <param name="Q"></param>
        /// <returns></returns>
        public IQueryable<T> Where(IDictionary<string, object> Q) {
            return Mquery.Find(new QueryDocument(Q)).AsQueryable();
        }
        public IQueryable<T> Where(IMongoQuery Q)
        {
            return Mquery.Find(Q).AsQueryable();
        }
        public T GetById(string id)
        {   if(string.IsNullOrWhiteSpace(id)){return null;}
            return Mquery.FindOneById(ObjectId.Parse(id));
        }
        public T GetById(BsonValue id)
        {
            return Mquery.FindOneById(id);
        }
        public T Get(IMongoQuery imq) {

            return Mquery.FindOne(imq);
        }
        public T Get(string field,string value)
        {
            return Mquery.FindOne(new QueryDocument(field, value));
        }
        public T Get(Func<T,Boolean> lambda) {
            return query.Where(lambda).FirstOrDefault();
        }
        /// <summary>
        /// 原生等于查询
        /// </summary>
        /// <param name="field"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public IQueryable<T> Where(string field, string value)
        {
            return Mquery.Find(new QueryDocument(getMongoMapField(field,typeof(T)), value)).AsQueryable();
        }
        /// <summary>
        /// 原生模糊查询
        /// </summary>
        /// <param name="field">字段名（类中成员变量名，非数据库）</param>
        /// <param name="regxStr">正则表达式字符串</param>
        /// <returns></returns>
        public IQueryable<T> like(string field,string regxStr) {
            System.Text.RegularExpressions.Regex regx = new System.Text.RegularExpressions.Regex(regxStr, System.Text.RegularExpressions.RegexOptions.Compiled);
            return like(field, regx);
        }
        /// <summary>
        /// 原生模糊查询
        /// </summary>
        /// <param name="field">字段名（类中成员变量名，非数据库）</param>
        /// <param name="regxStr">正则表达式</param>
        /// <returns></returns>
        public IQueryable<T> like(String field,System.Text.RegularExpressions.Regex regx)
        {
            
            return Mquery.Find(Query.EQ(getMongoMapField(field,typeof(T)), regx)).AsQueryable();
        }

        /// <summary>
        /// 取得数据库映射的字段名
        /// </summary>

        /// <returns></returns>
        public string getMongoMapField(string str, Type classType)
        {
            return BsonClassMap.LookupClassMap(classType).GetMemberMap(str).ElementName;
        }
        public IQueryable<Object> Select(System.Linq.Expressions.Expression<Func<T, Object>> lambda)
        {
            return query.Select(lambda);
        }
        public IQueryable<Object> Select(IDictionary<string, object> Q)
        {
            return Mquery.FindAs<Object>(new QueryDocument(Q)).AsQueryable();
        }
        public void AddRange(IEnumerable<T> t) {
            Mquery.InsertBatch(t);
        }
        public T Add(T t)
        {
            Mquery.Insert(t);
            return t;
        }
        public void Save(T t)
        {
            Mquery.Save(t);
        }
        public void Updata(IMongoQuery imq, IMongoUpdate imu)
        {
            Mquery.Update(imq, imu);
        }
        public void Delete(string id) { 
            Mquery.Remove(new QueryDocument("_id",ObjectId.Parse(id)));
        }
        public void Delete(ObjectId Id) {
             Mquery.Remove(new QueryDocument("_id", Id));
        }
        public void Delete(IDictionary<string, object> Q)
        {
             Mquery.Remove(new QueryDocument(Q));
        }
        public long count() {
            return Mquery.Count();
        }
        public long count(IDictionary<string,object> Q) {

            QueryDocument q = new QueryDocument(Q);

            return Mquery.Count(q);
        }
        public long count(IMongoQuery Q)
        {
            return Mquery.Count(Q);
        }
        public long qCount(Func<T, Boolean> lambda)
        {
            return query.Count(lambda);
        }      
    }
    public class MongoDataContext{
        public MongoDatabase mdb;
        public MongoDataContext()
        {
            string _connectionString = System.Configuration.ConfigurationManager.AppSettings["MongoDBConnectionString"];

            if (string.IsNullOrWhiteSpace(_connectionString))
                throw new Exception() { }; //new asMeishiException("数据库连接字符串未设置！");

            MongoServer server = MongoServer.Create(_connectionString);

            mdb = server.GetDatabase("duanzhi");
            
        }
    }
    public class MongoDocument {
        [BsonId]
        //[BsonDefaultValue("_id")]
        public ObjectId Id { set; get; }
    }
    public enum IndexOrder
    {
        /// <summary>
        /// 
        /// </summary>
        Descending = -1,
        /// <summary>
        /// 
        /// </summary>
        Ascending = 1
    }
    public static class MongoExtClass{

        public static ObjectId toOId(this String str)
        {
            return ObjectId.Parse(str);
        }
    }

}